package log

import (
	"io/ioutil"
	stdLog "log" // 防止命名冲突
	"net/http"
	"os"
)

// server.go 是日志服务的后端逻辑

// 这个日志服务是一个 Web 服务
// 它可以接收 POST 请求，然后把请求中的内容写入到 log 中

var log *stdLog.Logger

// 写入文件的路径
type fileLog string

// 写入数据，返回写入的数据量
// 只有实现了 Write(p []byte) (n int, err error)，才算实现的 io.Writer 接口
func (fl fileLog) Write(data []byte) (int, error) {
	// 打开这个文件
	// 需要把 fl 转换为 string 类型，作为 OpenFile 的第一个参数
	// os.O_CREATE 若文件不存在，则创建一个
	// os.O_WRONLY 打开这个文件时，只写入
	// os.O_APPEND 写入的数据是往后附加的
	// 0600 这个程序可能会运行在其他系统上，为了保持一惯性
	f, err := os.OpenFile(string(fl), os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0600)
	if err != nil {
		return 0, err
	}
	defer f.Close()
	return f.Write(data)
}

// Run 当运行自定义 log 时，让这个 log 指向某一个文件地址
func Run(destination string) {
	// 创建一个新的 Logger
	// New 的第一个参数是要实现 io.Writer 接口
	// prefix 是前缀
	// flag 会定义日志的属性，LstdFlags 是标准 logger 的初始属性，长日期和长时间
	log = stdLog.New(fileLog(destination), "[go] - ", stdLog.LstdFlags)
}

func RegisterHandlers() {
	http.HandleFunc("/log", func(w http.ResponseWriter, r *http.Request) {
		// 判断方法类型
		switch r.Method {
		case http.MethodPost:
			// 读取请求体，此时 msg 类型为 []byte
			msg, err := ioutil.ReadAll(r.Body)
			if err != nil || len(msg) == 0 {
				w.WriteHeader(http.StatusBadRequest) // 400
				return
			}

			// 将数据写入进去
			write(string(msg))
		default:
			w.WriteHeader(http.StatusMethodNotAllowed) // 405
			return
		}
	})
}

// 将数据写入进日志中
func write(message string) {
	log.Printf("%v\n", message)
}
